home *** CD-ROM | disk | FTP | other *** search
- Path: qualcomm.com!usenet
- From: nabbasi@qualcomm.com (Nasser Abbasi)
- Newsgroups: comp.programming.threads,comp.lang.c++,comp.unix.osf.osf1,comp.unix.programmer,comp.object
- Subject: Re: Looking for best design for using pthreads in C++ objects
- Date: 20 Feb 1996 08:00:51 GMT
- Organization: QUalcomm Inc.
- Message-ID: <4gbv3j$g08@qualcomm.com>
- References: <3128ff8b.666031216@news.clark.net>
- Reply-To: x!news.be.innet.net!INbe.net!usenet
- NNTP-Posting-Host: annex-p15.qualcomm.com
- X-Newsreader: WinVN 0.90.4
-
- In article <3128ff8b.666031216@news.clark.net>, anderson@clark.net (Thom Anderson) says:
- >
- >I am starting to port a design that was meant to be implemented in Ada to a
- >C++/UNIX platform. I don't want to get involved in any language religion here,
- >but it will be much harder to handle tasking with C++. My best alternative
- >(maybe only - since I must be POSIX compliant) is to use pthreads.
- >
- >I have used pthreads from C before but not from C++. I have a couple of ideas
- >in mind but neither is elegant. Does anyone have any experience with
- >C++/Pthreads and no of some good design solutions, tips, or ideas???
- >
-
- I have implemented a C++ Base Thread class that allows threads cross
- communications using message queues.
-
- The idea is that you have a base thread class, with public interface
- access functions to create a thread (can be implemented using Pthread
- or whatever thread package you have), and to READ/WRITE from thread
- Input and Output Queues. You also need to have a pure virtual
- function that is the address of thread function code itself which the
- derived classes have to provide. This way each specialized class can use
- different thread functions.
-
- Now, assume you have created 2 threads objects, A and B. A uses function
- A_foo() as the thread function, and B say uses B_foo() as the B thread
- function.
-
- For A to send a message to B, A will invoke a public access function in B
- that will deposit a message inside a private Queue in B and will then wake
- up B (B thread id is saved in private part of B class object )and return.
-
- Each thread can once in a while can check its input Queue to see if it has
- messages to process. If no message, it will sleep until awakened (or
- sleep for certain period, then tries again etc...).
-
- If you want to implement a driver type of thread, (passive thread) you can
- also have the thread object contain an output Queue (in addition to
- Input Queue), and the thread will deposit processed messages (work
- completed) in its output Queue and will then wake any waiting thread on
- its output Queue (the readers). (in first-in-first_out fashion).
-
- Each reader will invoke a READ access public function in the thread class,
- where this READ access function will access the thread private output
- Queue and if there is data, it will remove it, and return, else it will
- sleep (block) on the Queue (saves its thread_id in waiters Queue) so
- that when the driver thread has data to send out, it will put it in its
- output Queue, check the waiters/readers queue, wake up the first in
- line using the reader thread_id). Offcourse you do not have to have
- the read block if there is no data. you can have a time_out value, or
- other combination.
-
- I do not know Pthreads much, so I do not know if you also need some
- kind of signal number to use in addition to the thread_id to wake up
- a thread (You need to look at the Pthread Wake thread API), but if you
- do, that is easy to also pass along with the thread_id to allow the
- other thread to wake your thread. (i.e. each Input and Output Queue
- for each thread will have a signal number associated with it).
-
- All in All, you need to spend good time designing the thread class,
- and hide all the threads-cross communications in the private part of
- the class. Using Queues to accomplish the message exchanging is the
- most natural way.
-
- One thing to worry about is how much time a caller thread will spend
- in the access function of the other thread object. While executing
- the access function inside one thread object the client thread is
- executing in its own context ,which might have higher priority that
- the called thread object, and so things like blocking inside the
- access function need to be thought out well to make sure that is
- what you want to do. (to prevent among other things possible dead-lock).
-
- It is really not that hard, I have implemented the complete class in about
- 1-2 week, it is 3 layers in class hierarchy, and it is about 500-600
- lines of code (and this was the first time I looked at this problem
- of using C++ classes and threads.
-
- offcourse you need to have access to thread-safe Queue classes.
-
- If you on the other hand decide to use Ada , you'll have easier time,
- since Ada as you know already solves many of these problems for you,
- by providing tasks and protected objects, the Requeue facility, Rendezvous,
- Asynchronous transfer of control, and many other features for
- task-to-task interactions.
-
- Nasser
-